﻿using DocumentFormat.OpenXml.Packaging;
using Presentation=DocumentFormat.OpenXml.Presentation;
using Drawing=DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml;
using A = DocumentFormat.OpenXml.Drawing;
using P15 = DocumentFormat.OpenXml.Office2013.PowerPoint;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using Thm15 = DocumentFormat.OpenXml.Office2013.Theme;
using Ap = DocumentFormat.OpenXml.ExtendedProperties;
using Vt = DocumentFormat.OpenXml.VariantTypes;
using System.IO;
using System;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using wpfRectangle=System.Windows.Shapes.Rectangle;
using wBrushes = System.Windows.Media.Brushes;
using System.Windows.Media;
using Path=System.Windows.Shapes.Path;
using wShapes = System.Windows.Shapes;
using System.Threading;
using static PPTHelper.BLL.ShapeGeometryHelper;
using static PPTHelper.BLL.ShapeGuideFormula;
using PPTHelper.BLL.TimingRoot;
using PPTHelper.BLL;
using PPTHelper.BLL.TimingRoot.Controller_;

namespace PPTHelper.BLL
{
    public class PptDecoder
    {
        private PresentationDocument _context;

        /// <summary>
        /// 打开一个PPT文件
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="isEditable">是否可编辑</param>
        public PresentationDocument OpenPptFile(string path, bool isEditable)
        {
            if (File.Exists(path) is false)
            {
                throw new Exception("文件路径错误或不存在！");

            }
            return _context = PresentationDocument.Open(path, isEditable);
        }

        /// <summary>
        /// PPT幻灯片转换成区域
        /// </summary>
        /// <param name="document"></param>
        /// <returns></returns>
        public Collection<ContentControl> SlidesConvertToRegions(PresentationDocument document)
        {
            var presentation= document.PresentationPart;

            var slidePart = presentation.SlideParts.FirstOrDefault<SlidePart>();

            // 只读取第一张幻灯片
            // 读取所有能解析的形状
            //var shapeinfos = GetPathsFromSlide(slidePart.Slide);

            TimeNodeBuilder timeNodeBuilder = new TimeNodeBuilder();
            var root = timeNodeBuilder.BuildTimingRoot(slidePart.Slide.Timing);
            root.StartInit();

            //TimingRootController timingRootController = new TimingRootController(slidePart.Slide.Timing);

            // 获取动画，并执行动画
            //var container = GetAnimateFromSlide(slidePart.Slide);
            //container?.Run();

            return null;
        }

        /// <summary>
        /// 解析PPT动画
        /// </summary>
        /// <param name="slide"></param>
        /// <returns></returns>
        private TimeNodeContainer GetAnimateFromSlide(Presentation.Slide slide)
        {
            // 获取时序树的根
            Presentation.Timing timing = slide.Timing;

            // 获取时间节点列表
            Presentation.TimeNodeList timeNodeList = timing.TimeNodeList;

            //foreach (OpenXmlElement timeNode in timeNodeList)
            //{
            //    // 三种类型的动画容器
            //    //Presentation.ParallelTimeNode
            //    //Presentation.SequenceTimeNode
            //    //Presentation.ExclusiveTimeNode

            //    var container = timeNode.Elements<Presentation.ParallelTimeNode>();

            //    DecodeTimeNodeContainer(container);
            //}
            Presentation.ParallelTimeNode par = timeNodeList.GetFirstChild<Presentation.ParallelTimeNode>();
            ParallelContainer parallelcontainer = GetParallelContainer(par);
            //PrintContainer(parallelcontainer, "");

            return null;
        }

        ///// <summary>
        ///// 打印容器
        ///// </summary>
        ///// <param name="container"></param>
        ///// <param name="index"></param>
        //private void PrintContainer(TimeNodeContainer container, string index)
        //{
        //    Console.WriteLine(index + container.GetType().Name);
        //    index += "\t";

        //    foreach (var item in container.TimeNodeList)
        //    {
        //        PrintContainer(item, index);
        //    }
        //}

        /// <summary>
        /// 设置动画时间节点容器
        /// </summary>
        /// <param name="container">容器</param>
        /// <param name="nodeList">需要关联的子容器</param>
        void SetTimeNodeContainer(TimeNodeContainer container, Presentation.ChildTimeNodeList nodeList)
        {
            if (nodeList == null)
                return;

            TimeNodeContainer tmp = null;
            foreach (var timeNode in nodeList)
            {
                if (timeNode is Presentation.ParallelTimeNode parNode)
                {
                    tmp = GetParallelContainer(parNode);
                }
                else
                if (timeNode is Presentation.SequenceTimeNode seqNode)
                {
                    tmp = GetSequenceContainer(seqNode);
                }
                else
                if (timeNode is Presentation.SetBehavior setNode)
                {
                    //tmp = GetSetBehaviorContainer(setNode);
                }
                else 
                if (timeNode is Presentation.Animate animate)
                {
                    //tmp = GetAnimationContainer(animate);
                }

                if (tmp != null)
                {
                    // 设置父亲节点
                    container.Parent = container;

                    // 添加子节点
                    container.TimeNodeList.Add(tmp);
                }
            }
        }

        ///// <summary>
        ///// 获取Animate容器
        ///// </summary>
        ///// <param name="timeNodeContainer"></param>
        ///// <returns></returns>
        //AnimationContainer GetAnimationContainer(Presentation.Animate timeNodeContainer)
        //{
        //    var cb = timeNodeContainer.CommonBehavior;

        //    AnimationContainer animation = new AnimationContainer();

        //    if (cb != null)
        //    {
        //        animation.CommonBehavior = cb;
               
        //        if (cb.CommonTimeNode != null)
        //        {
        //            animation.CommonTimeNode = cb.CommonTimeNode;
        //            SetTimeNodeContainer(animation, cb.CommonTimeNode.ChildTimeNodeList);
        //        }
        //    }
        //    return animation;
        //}

        ///// <summary>
        ///// 获取SetBehavior容器
        ///// </summary>
        ///// <param name="timeNodeContainer"></param>
        ///// <returns></returns>
        //SetBehaviorContainer GetSetBehaviorContainer(Presentation.SetBehavior timeNodeContainer)
        //{
        //    var cb = timeNodeContainer.CommonBehavior;

        //    SetBehaviorContainer setBehavior = new SetBehaviorContainer();

        //    if (cb != null)
        //    {
        //        setBehavior.CommonBehavior = cb;

        //        if (cb.CommonTimeNode != null)
        //        {
        //            setBehavior.CommonTimeNode = cb.CommonTimeNode;
        //            SetTimeNodeContainer(setBehavior, cb.CommonTimeNode.ChildTimeNodeList);
        //        }
        //    }

        //    return setBehavior;
        //}

        /// <summary>
        /// 获取并行动画容器
        /// </summary>
        /// <param name="timeNodeContainer">动画容器</param>
        ParallelContainer GetParallelContainer(Presentation.ParallelTimeNode timeNodeContainer)
        {
            var ctn = timeNodeContainer.CommonTimeNode;
            
            ParallelContainer parallel = new ParallelContainer();
            parallel.CommonTimeNode = ctn;

            SetTimeNodeContainer(parallel, ctn.ChildTimeNodeList);

            return parallel;
        }

        //SetBehaviorContainer GetSetBehaviorContainer(Presentation.SequenceTimeNode timeNodeContainer)
        //{
        //    var ctn = timeNodeContainer.CommonTimeNode;

        //    SetBehaviorContainer setBehavior = new SetBehaviorContainer();
        //    setBehavior.CommonTimeNode = ctn;

        //    return setBehavior;

            

        //}

        /// <summary>
        /// 获取序列动画容器
        /// </summary>
        /// <param name="timeNodeContainer">动画容器</param>
        /// <returns></returns>
        SequenceContainer GetSequenceContainer(Presentation.SequenceTimeNode timeNodeContainer)
        {
            var ctn = timeNodeContainer.CommonTimeNode;

            SequenceContainer sequence = new SequenceContainer();
            sequence.CommonTimeNode = ctn;

            SetTimeNodeContainer(sequence, ctn.ChildTimeNodeList);

            return sequence;
        }

        /// <summary>
        /// 获取所有的几何形状
        /// </summary>
        /// <param name="slide"></param>
        /// <returns></returns>
        public Collection<ElementInfo> GetPathsFromSlide(Presentation.Slide slide)
        {
            var window = new Window() { WindowStartupLocation = WindowStartupLocation.CenterScreen, Height = 800, Width = 800 / 0.618, Title = "MainWindow" };
            var canvas = new Canvas();
            window.Content = canvas;
             
            // 获取所有形状
            IEnumerable<Presentation.Shape> shapes = GetShapesOfSlide(slide);

            Collection<ElementInfo> shapeInfos = new Collection<ElementInfo>();

            //ShapeConvertToUiElement(shapes.LastOrDefault<Presentation.Shape>());

            foreach (var shape in shapes)
            {
                ElementInfo shapeInfo = GetShapeInfo(shape);
                
                if (shapeInfo != null)
                {
                    canvas.Children.Add(shapeInfo.UIElement);
                    shapeInfos.Add(shapeInfo);
                }
            }

            window.ShowDialog();
            return shapeInfos;
        }


        public void GetShapeAnimation(Presentation.Slide slide)
        {
            

        }



        /// <summary>
        /// 把一个Shape转换成Path元素
        /// </summary>
        /// <param name="shape"></param>
        /// <returns></returns>
        private ElementInfo GetShapeInfo(Presentation.Shape shape)
        {
             // 获取形状的属性
            var shapeProperties = shape.ShapeProperties;
            var shapeInfo = new ElementInfo();

            shapeInfo.Id = shape.NonVisualShapeProperties.NonVisualDrawingProperties.Id;

            #region 设置左边和尺寸

            // 获取形状的左边和尺寸
            var xfrm = shapeProperties.Transform2D;

            // 矩形的起点
            var startPoint = new Point(new Emu(xfrm.Offset.X).ToPixel().Value, new Emu(xfrm.Offset.Y).ToPixel().Value);
            var width = new Emu(xfrm.Extents.Cx).ToPixel().Value;
            var height = new Emu(xfrm.Extents.Cy).ToPixel().Value;
        
            #endregion

            #region 获取预设几何

            var presetGeometry = shapeProperties.GetFirstChild<Drawing.PresetGeometry>();

            if (presetGeometry != null && presetGeometry.Preset.HasValue)
            {
                // 五边形
                if (presetGeometry.Preset == Drawing.ShapeTypeValues.Pentagon)
                {
                    Path path = GetPentagongPath(width, height);
                    path.Stroke = wBrushes.Red;
                    path.StrokeThickness = 2;
               
                    Canvas.SetLeft(path, startPoint.X);
                    Canvas.SetTop(path, startPoint.Y);
                    shapeInfo.UIElement = path;

                    return shapeInfo;
                }
                else
                // 圆角矩形
                if (presetGeometry.Preset == Drawing.ShapeTypeValues.RoundRectangle)
                {

                    Path path = GetRoundRectanglePath(width, height);

                    path.Stroke = wBrushes.Green;
                    path.StrokeThickness = 2;
                   
                    Canvas.SetLeft(path, startPoint.X);
                    Canvas.SetTop(path, startPoint.Y);
                    shapeInfo.UIElement = path;

                    return shapeInfo;
                }
                else
                // 立体几何
                if (presetGeometry.Preset == Drawing.ShapeTypeValues.Cube)
                {
                    Path path = GetCubePath(width, height);

                    path.Stroke = wBrushes.Blue;
                    path.StrokeThickness = 2;
                  
                    Canvas.SetLeft(path, startPoint.X);
                    Canvas.SetTop(path, startPoint.Y);
                    shapeInfo.UIElement = path;

                    return shapeInfo;
                }
                else 
                // 十字形
                if (presetGeometry.Preset == Drawing.ShapeTypeValues.Plus)
                {
                    wShapes.Path newPath = GetPlusPath(width, height);
                    newPath.Stroke = wBrushes.DarkOrange;
                    newPath.StrokeThickness = 2;

                    Canvas.SetLeft(newPath, startPoint.X);
                    Canvas.SetTop(newPath, startPoint.Y);
                    shapeInfo.UIElement = newPath;

                    return shapeInfo;
                }

            }

            #endregion
            return null;
        }

        private wShapes.Path GetPlusPath(double width, double height)
        {
            wShapes.Path path = new Path();

            var prop = new FormulaProperties(width, height);
            const double adj = 25000;

            //<gd name="a" fmla="pin 0 adj 50000" />
            var a = PinTo(0, adj, 50000);
            //<gd name="x1" fmla="*/ ss a 100000" />
            var x1 = MultiplyDivide(prop.ss, a, 100000);
            //<gd name="x2" fmla="+- r 0 x1" />
            var x2 = AddSubtract(prop.r, 0, x1);
            //<gd name="y2" fmla="+- b 0 x1" />
            var y2 = AddSubtract(prop.b, 0, x1);
            //<gd name="d" fmla="+- w 0 h" />
            var d = AddSubtract(prop.w, 0, prop.h);
            //<gd name="il" fmla="?: d l x1" />
            var il = IfElse(d, prop.l, x1);
            //<gd name="ir" fmla="?: d r x2" />
            var ir = IfElse(d, prop.r, x2);
            //<gd name="it" fmla="?: d x1 t" />
            var it = IfElse(d, x1, prop.t);
            //<gd name="ib" fmla="?: d y2 b" />
            var ib = IfElse(d, y2, prop.b);

            StreamGeometry geometry = new StreamGeometry();
            using(StreamGeometryContext context = geometry.Open())
            {
                //<moveTo>
                // <pt x="l" y="x1" />
                //</moveTo>
                context.BeginFigure(new Point(prop.l, x1), false, true);
                //<lnTo>
                //  <pt x="x1" y="x1" />
                //</lnTo>
                context.LineTo(new Point(x1, x1), true, false);
                //<lnTo>
                //  <pt x="x1" y="t" />
                //</lnTo>
                context.LineTo(new Point(x1, prop.t), true, false);
                //<lnTo>
                //  <pt x="x2" y="t" />
                //</lnTo>
                context.LineTo(new Point(x2, prop.t), true, false);
                //<lnTo>
                //  <pt x="x2" y="x1" />
                //</lnTo>
                context.LineTo(new Point(x2, x1), true, false);
                //<lnTo>
                //  <pt x="r" y="x1" />
                //</lnTo>
                context.LineTo(new Point(prop.r, x1), true, false);
                //<lnTo>
                //  <pt x="r" y="y2" />
                //</lnTo>
                context.LineTo(new Point(prop.r, y2), true, false);
                //<lnTo>
                //  <pt x="x2" y="y2" />
                //</lnTo>
                context.LineTo(new Point(x2, y2), true, false);
                //<lnTo>
                //  <pt x="x2" y="b" />
                //</lnTo>
                context.LineTo(new Point(x2, prop.b), true, false);
                //<lnTo>
                //  <pt x="x1" y="b" />
                //</lnTo>
                context.LineTo(new Point(x1, prop.b), true, false);
                //<lnTo>
                //  <pt x="x1" y="y2" />
                //</lnTo>
                context.LineTo(new Point(x1, y2), true, false);
                //<lnTo>
                //  <pt x="l" y="y2" />
                //</lnTo>
                context.LineTo(new Point(prop.l, y2), true, false);
                //<close />
            }
            path.Data = geometry;
            return path;
        }

        /// <summary>
        /// 获取立方体的几何
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private wShapes.Path GetCubePath(double width, double height)
        {
            var prop = new FormulaProperties(width, height);
            const double adj = 25000;

            // <gdLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
            //  <gd name="a" fmla="pin 0 adj 100000" />
            var a = PinTo(0, adj, 100000);
            //  <gd name="y1" fmla="*/ ss a 100000" />
            var y1 = MultiplyDivide(prop.ss, a, 100000);
            //  <gd name="y4" fmla="+- b 0 y1" />
            var y4 = AddSubtract(prop.b, 0, y1);
            //  <gd name="y2" fmla="*/ y4 1 2" />
            var y2 = MultiplyDivide(y4, 1, 2);
            //  <gd name="y3" fmla="+/ y1 b 2" />
            var y3 = AddDivide(y1, prop.b, 2);
            //  <gd name="x4" fmla="+- r 0 y1" />
            var x4 = AddSubtract(prop.r, 0, y1);
            //  <gd name="x2" fmla="*/ x4 1 2" />
            var x2 = MultiplyDivide(x4, 1, 2);
            //  <gd name="x3" fmla="+/ y1 r 2" />
            var x3 = AddDivide(y1, prop.r, 2);
            // </gdLst>

            GeometryGroup group = new GeometryGroup();

            StreamGeometry geometry1 = new StreamGeometry();
            
            using (StreamGeometryContext context = geometry1.Open())
            {
                context.BeginFigure(new Point(prop.l, y1), false, true);
                context.LineTo(new Point(x4, y1), true, false);
                context.LineTo(new Point(x4, prop.b), true, false);
                context.LineTo(new Point(prop.l, prop.b), true, false);
            }
            group.Children.Add(geometry1);

            StreamGeometry geometry2 = new StreamGeometry();
            using (StreamGeometryContext context = geometry2.Open())
            {
                context.BeginFigure(new Point(x4, y1), false, true);
                context.LineTo(new Point(prop.r, prop.t), true, false);
                context.LineTo(new Point(prop.r, y4), true, false);
                context.LineTo(new Point(x4, prop.b), true, false);
            }
            group.Children.Add(geometry2);

            StreamGeometry geometry3 = new StreamGeometry();
            using (StreamGeometryContext context = geometry3.Open())
            {
                context.BeginFigure(new Point(prop.l, y1), false, true);
                context.LineTo(new Point(y1, prop.t), true, false);
                context.LineTo(new Point(prop.r, prop.t), true, false);
                context.LineTo(new Point(x4, y1), true, false);
            }
            group.Children.Add(geometry3);

            StreamGeometry geometry4 = new StreamGeometry();
            using (StreamGeometryContext context = geometry4.Open())
            {
                //context.BeginFigure(new Point(prop.l, y1), false, true);
                //context.LineTo(new Point(y1, prop.t), false, false);
                //context.LineTo(new Point(prop.r, prop.t), false, false);
                //context.LineTo(new Point(prop.r, y4), false, false);
                //context.LineTo(new Point(x4, prop.b), false, false);
                //context.LineTo(new Point(prop.l, prop.b), false, false);
               
                

                //context.BeginFigure(new Point(prop.l, y1), false, true);
                //context.LineTo(new Point(x4, y1), true, false);
                //context.LineTo(new Point(prop.r, prop.t), true, false);

                //context.BeginFigure(new Point(x4, y1), false, true);
                //context.LineTo(new Point(x4, prop.b), true, false);
            }
            group.Children.Add(geometry4);

            return new wShapes.Path() { Data = group };
        }

        /// <summary>
        /// 获取圆角矩形的几何
        /// </summary>
        /// <param name="width">Pixel的宽度值</param>
        /// <param name="height">Pixel的高度值</param>
        /// <returns></returns>
        private wShapes.Path GetRoundRectanglePath(double width, double height)
        {
            var properties = new FormulaProperties(width, height);

            const double adj = 16667;

            #region gdLst

            // pin 0 adj 50000
            var a = PinTo(0, adj, 5000);

            // */ ss a 100000
            var x1 = MultiplyDivide(properties.ss, a, 100000);

            // +- r 0 x1
            var x2 = AddSubtract(properties.r, 0, x1);

            // +- b 0 x1
            var y2 = AddSubtract(properties.b, 0, x1);

            // */ x1 29289 100000
            var il = MultiplyDivide(x1, 29289, 100000);

            var ir = AddSubtract(properties.r, 0, il);

            var ib = AddSubtract(properties.b, 0, il);

            #endregion

            var geometry = new StreamGeometry();

            using (StreamGeometryContext context = geometry.Open())
            {

                //<path>
                //  <moveTo>
                //    <pt x="l" y="x1" />
                //  </moveTo>
                //  <arcTo wR="x1" hR="x1" stAng="cd2" swAng="cd4" />
                //  <lnTo>
                //    <pt x="x2" y="t" />
                //  </lnTo>
                //  <arcTo wR="x1" hR="x1" stAng="3cd4" swAng="cd4" />
                //  <lnTo>
                //    <pt x="r" y="y2" />
                //  </lnTo>
                //  <arcTo wR="x1" hR="x1" stAng="0" swAng="cd4" />
                //  <lnTo>
                //    <pt x="x1" y="b" />
                //  </lnTo>
                //  <arcTo wR="x1" hR="x1" stAng="cd4" swAng="cd4" />
                //  <close />
                //</path>


                context.BeginFigure(new Point(properties.l, x1), false, true);
                context.ArcTo(new Point(properties.l + x1, x1 - x1), new Size(x1, x1), 0, false, SweepDirection.Clockwise, true, false);

                context.LineTo(new Point(x2, properties.t), true, false);
                context.ArcTo(new Point(x2 + x1, properties.t + x1), new Size(x1, x1), 0, false, SweepDirection.Clockwise, true, false);

                context.LineTo(new Point(properties.r, y2), true, false);
                context.ArcTo(new Point(properties.r - x1, y2 + x1), new Size(x1, x1), 0, false, SweepDirection.Clockwise, true, false);

                context.LineTo(new Point(x1, properties.b), true, false);
                context.ArcTo(new Point(x1 - x1, properties.b - x1), new Size(x1, x1), 0, false, SweepDirection.Clockwise, true, false);
            }

            return new wShapes.Path() { Data = geometry };
        }


        /// <summary>
        /// 获取五边形几何
        /// </summary>
        /// <param name="width">Pixel的宽度值</param>
        /// <param name="height">Pixel的高度值</param>
        /// <returns></returns>
        /// 该五边形定义出自ECMA-376-Fifth-Edition-Part-1-Fundamentals-And-Markup-Language-Reference
        /// \OfficeOpenXML-DrawingMLGeometries文档的presetShapeDefinitions.xml
        private wShapes.Path GetPentagongPath(double width, double height)
        {
            var properties = new FormulaProperties(width, height);

            //<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
            //  <gd name="hf" fmla="val 105146" />
            //  <gd name="vf" fmla="val 110557" />
            //</avLst>
            var hf = 105146d;
            var vf = 110557d;

            //<gdLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
            //  <gd name="swd2" fmla="*/ wd2 hf 100000" />
            //  <gd name="shd2" fmla="*/ hd2 vf 100000" />
            //  <gd name="svc" fmla="*/ vc  vf 100000" />
            //  <gd name="dx1" fmla="cos swd2 1080000" />
            //  <gd name="dx2" fmla="cos swd2 18360000" />
            //  <gd name="dy1" fmla="sin shd2 1080000" />
            //  <gd name="dy2" fmla="sin shd2 18360000" />
            //  <gd name="x1" fmla="+- hc 0 dx1" />
            //  <gd name="x2" fmla="+- hc 0 dx2" />
            //  <gd name="x3" fmla="+- hc dx2 0" />
            //  <gd name="x4" fmla="+- hc dx1 0" />
            //  <gd name="y1" fmla="+- svc 0 dy1" />
            //  <gd name="y2" fmla="+- svc 0 dy2" />
            //  <gd name="it" fmla="*/ y1 dx2 dx1" />
            //</gdLst>

            //  <gd name="swd2" fmla="*/ wd2 hf 100000" />
            var swd2 = MultiplyDivide(properties.wd2, hf, 100000);

            //  <gd name="shd2" fmla="*/ hd2 vf 100000" />
            var shd2 = MultiplyDivide(properties.hd2, vf, 100000);

            //  <gd name="svc" fmla="*/ vc  vf 100000" />
            var svc = MultiplyDivide(properties.vc, vf, 100000);

            //  <gd name="dx1" fmla="cos swd2 1080000" />

            var dx1 = Cosine(swd2, 1080000);
            //  <gd name="dx2" fmla="cos swd2 18360000" />
            var dx2 = Cosine(swd2, 18360000);
            //  <gd name="dy1" fmla="sin shd2 1080000" />
            var dy1 = Sine(shd2, 1080000);
            //  <gd name="dy2" fmla="sin shd2 18360000" />
            var dy2 = Sine(shd2, 18360000);
            //  <gd name="x1" fmla="+- hc 0 dx1" />
            var x1 = properties.hc - dx1;
            //  <gd name="x2" fmla="+- hc 0 dx2" />
            var x2 = properties.hc - dx2;
            //  <gd name="x3" fmla="+- hc dx2 0" />
            var x3 = properties.hc + dx2;
            //  <gd name="x4" fmla="+- hc dx1 0" />
            var x4 = properties.hc + dx1;
            //  <gd name="y1" fmla="+- svc 0 dy1" />
            var y1 = svc - dy1;
            //  <gd name="y2" fmla="+- svc 0 dy2" />
            var y2 = svc - dy2;
            //  <gd name="it" fmla="*/ y1 dx2 dx1" />

            // <pathLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
            //  <path>
            //    <moveTo>
            //      <pt x="x1" y="y1" />
            //    </moveTo>
            //    <lnTo>
            //      <pt x="hc" y="t" />
            //    </lnTo>
            //    <lnTo>
            //      <pt x="x4" y="y1" />
            //    </lnTo>
            //    <lnTo>
            //      <pt x="x3" y="y2" />
            //    </lnTo>
            //    <lnTo>
            //      <pt x="x2" y="y2" />
            //    </lnTo>
            //    <close />
            //  </path>
            //</pathLst>

            var geometry = new StreamGeometry();
            
            using (StreamGeometryContext context = geometry.Open())
            {
                context.BeginFigure(new Point(x1, y1), false, true);
                context.LineTo(new Point(properties.hc, properties.t), true, false);
                context.LineTo(new Point(x4, y1), true, false);
                context.LineTo(new Point(x3, y2), true, false);
                context.LineTo(new Point(x2, y2), true, false);
            }

            Path path = new Path();
            path.Stroke = wBrushes.Red;
            path.StrokeThickness = 2;

            path.Data = geometry;

            return path;
        }

        

      
        /// <summary>
        /// 获取Slide中的所有Shape元素
        /// </summary>
        /// <param name="slide"></param>
        /// <returns></returns>
        private IEnumerable<Presentation.Shape> GetShapesOfSlide(Presentation.Slide slide)
        {
            var commonSlideData= slide.GetFirstChild<Presentation.CommonSlideData>();

            var shapeTree = commonSlideData?.GetFirstChild<Presentation.ShapeTree>();

            return shapeTree.ChildElements.OfType<Presentation.Shape>();
        }

        /// <summary>
        /// 析构
        /// </summary>
        ~PptDecoder()
        {
            if (_context != null)
            {
                _context.Close();
            }
        }
    }
}
